/****************************************************************************
** \file LogLite.cpp
** \company PONGBOT
**
** \author houhaotian
** \date 2020/08/25
**
** \brief 在实例化QCoreApplication之后调用initLog，参数有路径和最大文件数量。
**        默认/log和100。随后即可在qDebug等qt调试宏中打印日志。
**  
**
****************************************************************************/
#include "LogLite.h"
#include <QCoreApplication>
#include <QDateTime>
#include <QMutex>
#include <QDir>
#include <iostream>
#include <QTextStream>
#include <QObject>

QString LogLite::m_logDir;//记录log路径
int LogLite::m_logMaxCount;//记录最大文件数
QFile LogLite::m_logFile;   //log文件句柄

LogLite::LogLite()
{
}

//在实例化QCoreApplication之后调用这个就可以
void LogLite::initLog(const QString &logdir, int logMaxCount)
{
    qInstallMessageHandler(myMessageOutput);

    m_logDir = QCoreApplication::applicationDirPath() + logdir;
    m_logMaxCount = logMaxCount;
    //检查存储文件夹，不存在则创建
    QDir dir(m_logDir);
    if (!dir.exists()) {
        dir.mkpath(dir.absolutePath());
    }
    //获取文件列表
    QStringList infoList = dir.entryList(QDir::Files, QDir::Name);
    //日志超过最大存储数，则删除最早的日志
    while (infoList.size() > m_logMaxCount) {
        dir.remove(infoList.first());
        infoList.removeFirst();
    }

    QObject::connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit, [] {
        m_logFile.close();
        });
}

void LogLite::myMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
    const char *file = context.file ? context.file : "";
    const char *function = context.function ? context.function : "";
    int line = context.line;
    QDateTime dt = QDateTime::currentDateTime();
    QString dateTime = dt.toString("yyyy-MM-dd HH:mm:ss.zzz").toLocal8Bit();
    QString text = QString(" %1 [file:%2 func:%3 line:%4] %5\r\n").arg(dateTime).arg(file).arg(function).arg(line).arg(msg);

    switch (type) {
    case QtDebugMsg:
        text.prepend("[DEBUG]");
        break;
    case QtInfoMsg:
        text.prepend("[INFO]");
        break;
    case QtWarningMsg:
        text.prepend("[WARNING]");
        break;
    case QtCriticalMsg:
        text.prepend("[CRITICAL]");
        break;
    case QtFatalMsg:
        text.prepend("[FATAL]");
        break;
    }

    //每天一个文件。
    QString fileName = QString("%1/%2.log").arg(m_logDir).arg(dt.toString("yyyy-MM-dd"));
    //每小时一个文件
    //QString fileName = dt.toString("yyyy-MM-dd-HH");
    static QTextStream stream;
    static QMutex mutex;
    QMutexLocker locker(&mutex);

    //如果根据日期设置的日志文件名和当前日志不同,
    //则关闭当前日志，打开新日志
    if (m_logFile.fileName() != fileName) {
        m_logFile.close();
        m_logFile.setFileName(fileName);
        m_logFile.open(QIODevice::WriteOnly | QIODevice::Append);
        stream.setDevice(&m_logFile);
        stream.setCodec("UTF-8");
    }

    stream << text;
    stream.flush();
    std::cout << msg.toStdString() << std::endl;
}
